home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / wrlib / gif.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-02-29  |  5.0 KB  |  226 lines

  1. /* gif.c - load GIF image from file
  2.  * 
  3.  *  Raster graphics library
  4.  * 
  5.  *  Copyright (c) 1998 Alfredo K. Kojima
  6.  *
  7.  *  This library is free software; you can redistribute it and/or
  8.  *  modify it under the terms of the GNU Library General Public
  9.  *  License as published by the Free Software Foundation; either
  10.  *  version 2 of the License, or (at your option) any later version.
  11.  *  
  12.  *  This library is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  *  Library General Public License for more details.
  16.  *  
  17.  *  You should have received a copy of the GNU Library General Public
  18.  *  License along with this library; if not, write to the Free
  19.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  */
  21.  
  22. #include <config.h>
  23.  
  24.  
  25. #ifdef USE_GIF
  26.  
  27. #include <stdlib.h>
  28. #include <stdio.h>
  29. #include <string.h>
  30.  
  31. #include <gif_lib.h>
  32.  
  33. #include "wraster.h"
  34.  
  35.  
  36. static int InterlacedOffset[] = { 0, 4, 2, 1 };
  37. static int InterlacedJumps[] = { 8, 8, 4, 2 };
  38.  
  39.  
  40. /*
  41.  * Partially based on code in gif2rgb from giflib, by Gershon Elber.
  42.  */
  43. RImage*
  44. RLoadGIF(RContext *context, char *file, int index)
  45. {
  46.     RImage *image = NULL;
  47.     unsigned char *cptr;
  48.     GifFileType *gif = NULL;
  49.     GifPixelType *buffer = NULL;
  50.     int i, j, k;
  51.     int width, height;
  52.     GifRecordType recType;
  53.     ColorMapObject *colormap;
  54.     unsigned char rmap[256];
  55.     unsigned char gmap[256];
  56.     unsigned char bmap[256];
  57.  
  58.     if (index < 0)
  59.     index = 0;
  60.  
  61.     /* default error message */
  62.     RErrorCode = RERR_BADINDEX;
  63.  
  64.     gif = DGifOpenFileName(file);
  65.     
  66.     if (!gif) {
  67.     switch (GifLastError()) {
  68.      case D_GIF_ERR_OPEN_FAILED:
  69.         RErrorCode = RERR_OPEN;
  70.         break;
  71.      case D_GIF_ERR_READ_FAILED:
  72.         RErrorCode = RERR_READ;
  73.         break;
  74.      default:
  75.         RErrorCode = RERR_BADIMAGEFILE;
  76.         break;
  77.     }
  78.     return NULL;
  79.     }
  80.  
  81.     colormap = gif->SColorMap;
  82.  
  83.     i = 0;
  84.     
  85.     do {
  86.     int extCode;
  87.     GifByteType *extension;
  88.  
  89.     if (DGifGetRecordType(gif, &recType) == GIF_ERROR) {
  90.         goto giferr;
  91.     }
  92.     switch (recType) {
  93.      case IMAGE_DESC_RECORD_TYPE:
  94.         if (i++ != index)
  95.         break;
  96.  
  97.         if (DGifGetImageDesc(gif)==GIF_ERROR) {
  98.         goto giferr;
  99.         }
  100.         
  101.         width = gif->Image.Width;
  102.         height = gif->Image.Height;
  103.         
  104.         if (gif->Image.ColorMap)
  105.         colormap = gif->Image.ColorMap;
  106.  
  107.         /* the gif specs talk about a default colormap, but it
  108.          * doesnt say what the heck is this default colormap */
  109.         if (!colormap) {
  110.         /*
  111.          * Well, since the spec says the colormap can be anything,
  112.          * lets just render it with whatever garbage the stack 
  113.          * has :)
  114.          * 
  115.         
  116.         goto bye;
  117.          */
  118.         } else {
  119.         for (j = 0; j < colormap->ColorCount; j++) {
  120.             rmap[j] = colormap->Colors[j].Red;
  121.             gmap[j] = colormap->Colors[j].Green;
  122.             bmap[j] = colormap->Colors[j].Blue;
  123.         }
  124.         }
  125.  
  126.         buffer = malloc(width * sizeof(GifColorType));
  127.         if (!buffer) {
  128.         RErrorCode = RERR_NOMEMORY;
  129.         goto bye;
  130.         }
  131.  
  132.         image = RCreateImage(width, height, False);
  133.         if (!image) {
  134.         goto bye;
  135.         }
  136.  
  137.         if (gif->Image.Interlace) {
  138.         int l;
  139.         int pelsPerLine;
  140.  
  141.         if (RRGBAFormat==image->format)
  142.             pelsPerLine = width * 4;
  143.         else
  144.             pelsPerLine = width * 3;
  145.  
  146.         for (j = 0; j < 4; j++) {
  147.             for (k = InterlacedOffset[j]; k < height;
  148.              k += InterlacedJumps[j]) {
  149.             if (DGifGetLine(gif, buffer, width)==GIF_ERROR) {
  150.                 goto giferr;
  151.             }
  152.             cptr = image->data + (k*pelsPerLine);
  153.             for (l = 0; l < width; l++) {
  154.                 int pixel = buffer[l];
  155.                 *cptr++ = rmap[pixel];
  156.                 *cptr++ = gmap[pixel];
  157.                 *cptr++ = bmap[pixel];
  158.             }
  159.             }
  160.         }
  161.         } else {
  162.         cptr = image->data;
  163.         for (j = 0; j < height; j++) {
  164.             if (DGifGetLine(gif, buffer, width)==GIF_ERROR) {
  165.             goto giferr;
  166.             }
  167.             for (k = 0; k < width; k++) {
  168.             int pixel = buffer[k];
  169.             *cptr++ = rmap[pixel];
  170.             *cptr++ = gmap[pixel];
  171.             *cptr++ = bmap[pixel];
  172.             if (RRGBAFormat==image->format)
  173.                 cptr++;
  174.             }
  175.         }
  176.         }
  177.         break;
  178.  
  179.      case EXTENSION_RECORD_TYPE:
  180.         /* skip all extension blocks */
  181.         if (DGifGetExtension(gif, &extCode, &extension)==GIF_ERROR) {
  182.         goto giferr;
  183.         }
  184.         while (extension) {
  185.         if (DGifGetExtensionNext(gif, &extension)==GIF_ERROR) {
  186.             goto giferr;
  187.         }
  188.         }
  189.         break;
  190.  
  191.      default:
  192.         break;
  193.     }
  194.     } while (recType != TERMINATE_RECORD_TYPE && i <= index);
  195.  
  196.     /* yuck! */
  197.     goto did_not_get_any_errors;
  198. giferr:
  199.     switch (GifLastError()) {
  200.      case D_GIF_ERR_OPEN_FAILED:
  201.     RErrorCode = RERR_OPEN;
  202.     break;
  203.      case D_GIF_ERR_READ_FAILED:
  204.     RErrorCode = RERR_READ;
  205.     break;
  206.      default:
  207.     RErrorCode = RERR_BADIMAGEFILE;
  208.     break;
  209.     }    
  210. bye:
  211.     if (image)
  212.     RDestroyImage(image);
  213.     image = NULL;
  214. did_not_get_any_errors:
  215.  
  216.     if (buffer)
  217.     free(buffer);
  218.  
  219.     if (gif)
  220.     DGifCloseFile(gif);
  221.  
  222.     return image;
  223. }
  224.  
  225. #endif /* USE_GIF */
  226.